<template>
  <div class="excel-import-page">
    <div class="excel-import-bar">
      <span>
        <span>选择文件：</span>
        <dg-upload
          action="#"
          ref="fileUploader"
          :multiple="true"
          :http-request="uploadFile"
          :show-file-list="false"
          :disabled="fileList.length != 0"
          :accept="supportType"
          size="30m"
          tip-msg="上传文件限制大小为 30M"
          style="display: inline-block; margin-right: 10px"
        >
          <slot name="upload-btn">
            <el-button :disabled="fileList.length != 0" icon="el-icon-upload2" style="text-align: none"
              >上传附件</el-button
            >
          </slot>
        </dg-upload>
        <span> </span>
      </span>
    </div>
    <div class="excel-import-status">
      <div v-for="(item, index) in fileList" :key="index">
        <dg-row class="excel-import-status-item">
          <dg-col :span="20">
            <span class="excel-import-status-info"
              >{{ item.fileName }}({{ parseFileSize(item.fileSize) }})-{{ item | getStatus }}</span
            >
            <el-progress :percentage="item.percentage"> </el-progress>
          </dg-col>
          <dg-col :span="4" style="margin-top: 12px">
            <dg-button
              size="mini"
              type="danger"
              icon="el-icon-delete"
              disabled
              circle
              v-if="item.id && item.uploadStatus == 0"
              title="上传中，不能删除"
            ></dg-button>
            <dg-button size="mini" type="danger" icon="el-icon-delete" circle v-else @click="handleDeleteFile(item)">
            </dg-button>
          </dg-col>
        </dg-row>
      </div>
    </div>
    <div class="excel-import-download-template">
      <slot name="template-btn">
        模板下载：
        <dg-button type="text" @click="handleDownloadTemplate">{{ typeName }}</dg-button>
      </slot>
    </div>
    <div v-footer>
      <dg-button @click="handleCancel">取消</dg-button>
      <dg-button type="primary" @click="handleImportAll" :disabled="!uploadInfo.success">导入</dg-button>
    </div>
  </div>
</template>
<script>
import ExcelImportApi from '@/api/excelImportApi';
import dateUtils from '@srcPath/utils/date-utils';
import clickoutside from 'raw-loader!babel-loader!ui-component-v4/lib/dg-directives/clickoutside';
import _ from '@srcPath/utils/zt-lodash';
import base64 from 'js-base64';

export default {
  name: 'DgExcelImport',
  props: {
    id: {
      // 导入方案id
      type: String,
      required: true
    },
    // 模板名称
    typeName: {
      type: String,
      default: '群体信息'
    },
    name: {
      // 导入方案名称，可以覆盖后台的配置
      type: String,
      default: ''
    },
    module: {
      // 请求api所属module
      type: String,
      default: 'IMPORT_API'
    },
    params: {
      // 导入业务参数，用于将一些特定参数传递给后台处理接口
      type: Object,
      default() {
        return {};
      }
    },
    fileLimitSize: {
      // 上传文件大小限制，单位：MB
      type: Number,
      default: 30
    },
    border: {
      // 表格是否显示边框
      type: Boolean,
      default: true
    },
    showLast: {
      // 是否显示上一次导入信息
      type: Boolean,
      default: true
    },
    showFileName: {
      // 数据列表是否显示文件名称
      type: Boolean,
      default: true
    },
    /**
     *表格列自定义处理函数，
     *可用于屏蔽某些列或自定义列,用于扩展列信息，会传入后台配置的列信息，前端可加列宽等
     */
    columnProcess: Function,
    columnWidths: {
      // 用于快速配置列宽，不配默认defaultColumnWidth：200
      type: Object,
      default() {
        return {};
      }
    }
  },
  data() {
    return {
      supportType: '.xls,.xlsx',
      scheme: {}, // 导入方案信息
      importSeq: -1,
      lastImportSeq: -1,
      fileList: [], // 导入文件列表
      uploadFiels: [], // 正在上传文件列表，分批次上传，不能全部上传，不然服务器压力过大
      parallelNum: 3, // 同时上传文件数量，同时上传三个文件，防止一次上传过多文件服务器崩掉
      uploadingNum: 0, // 正在上传中的数量
      loadingProcess: false,
      defaultColumnWidth: 490, // 列默认宽度
      editingRow: {}, // 正在编辑的行
      oriRow: {}, // 编辑前的原始行数据
      resultInfo: {
        fileCount: 0,
        total: 0,
        error: 0
      },
      fileResultMapper: {},
      gridCondition: {},
      gridOrder: {
        prop: 'id',
        order: 'ascending'
      },
      treeData: {},
      fieldMapper: {},
      tooltipDisabled: false,
      activeStatus: 'error',
      loadingBox: null,
      excelImportApi: new ExcelImportApi(this.module)
    };
  },
  computed: {
    uploadInfo() {
      let total = this.fileList.length;
      let success = 0;
      let error = 0;
      this.fileList.forEach(item => {
        if (item.uploadStatus === 1) {
          success++;
        }
        if (item.uploadStatus == 2) {
          error++;
        }
      });

      return {
        total: total,
        success: success,
        error: error
      };
    },
    fileMapper() {
      let mapper = {};
      this.fileList.forEach(item => {
        if (item.id) {
          mapper[item.id] = item;
        }
      });
      return mapper;
    },
    requestParams() {
      return {
        data: base64.Base64.encode(JSON.stringify(this.params))
      };
    }
  },
  filters: {
    getStatus(item) {
      if (!item.id) {
        return '待上传';
      }
      if (item.uploadStatus == 0) {
        return '上传中';
      }
      if (item.uploadStatus == 2) {
        return '上传失败';
      }
      if (item.uploadStatus == 1) {
        return '上传成功';
      }
    }
  },
  created() {
    if (this.id) {
      this.fetchImportScheme();
    } else {
      throw new Error('缺失id参数，excel导入方案id不能为空！');
    }
    // 加载进度条函数加入防抖功能
    this.loadFileProcess = _.debounce(this.loadFileProcess, 50);
    // 上传文件函数加入防抖功能，防止同时选择多个文件多次执行
    this.uploadFiles = _.debounce(this.doUploadFiles, 500);
    this.search = _.debounce(this.search, 500);
  },
  mounted() {
    this.$bus.$on('importAll', () => {
      this.handleImportAll(true);
    });
    this.$bus.$on('exportFailData', () => {
      this.handleExport();
    });
    this.$bus.$on('updateData', (editingRow, oriRow, dataSource) => {
      this.updateData(editingRow, oriRow, dataSource);
    });
  },
  beforeDestroy() {
    this.$bus.$off('closeErrorList');
    this.$bus.$off('importAll');
    this.$bus.$off('exportFailData');
    this.$bus.$off('updateData');
    this.$bus.$off('Success');
  },
  methods: {
    /**
     * 取消导入
     */
    handleCancel() {
      this.$emit('closeDialog');
    },
    /**
     * 表格查询
     */
    search() {
      this.gridCondition = {
        importSeq: {
          value: this.getCurrentImportSeq(),
          op: '='
        }
      };
      if (this.activeStatus == 'success') {
        this.gridCondition.validateStatus = {
          value: 1,
          op: '='
        };
      }
      if (this.activeStatus == 'error') {
        this.gridCondition.validateStatus = {
          value: 0,
          op: '='
        };
      }
      this.$nextTick(() => {
        // this.$refs.dataGrid.searchForm();
      });
      this.getImportStat();
    },

    /**
     * 获取导入方案信息
     */
    fetchImportScheme() {
      let that_ = this;
      that_.excelImportApi
        .getImportConfig(that_.id)
        .then(res => {
          that_.getImportSeq();
          that_.scheme = res.data;
          if (that_.name) {
            that_.scheme.name = that_.name;
          }
          let metadata = that_.scheme.metadata;
          if (that_.columnProcess) {
            let metadata = that_.columnProcess(metadata);
            metadata = metadata ? metadata : that_.scheme.metadata;
          }
          that_.scheme.metadata = metadata;

          that_.scheme.metadata.forEach(meta => {
            that_.$set(that_.fieldMapper, meta.name, meta);
            if (that_.columnWidths[meta.name]) {
              // 设置宽度
              that_.$set(meta, 'width', that_.columnWidths[meta.name]);
            }
          });

          that_.$bus.$emit('updateScheme', that_.scheme);

          that_.loadTreeData();
          if (that_.showLast) {
            that_.queryLastUploadInfo();
          }
        })
        .catch(that_.onException);
    },

    /**
     *获取树形选择数据
     */
    loadTreeData() {
      this.scheme.metadata.forEach(item => {
        if (item.isTree) {
          let codeId = item.format;
          this.treeData[codeId] = [];
          this.excelImportApi.listTreeData(item.type, codeId).then(res => {
            this.treeData[codeId] = res.data;
          });
        }
      });
    },

    /**
     * 获取导入序列号
     */
    getImportSeq() {
      this.excelImportApi
        .nextSequence()
        .then(resp => {
          this.importSeq = resp.data;
          if (!this.showLast) {
            // this.search();
          }
        })
        .catch(this.onException);
    },

    /**
     * 获取导入统计信息
     */
    getImportStat(isUpload) {
      this.excelImportApi
        .getImportStat(this.id, this.getCurrentImportSeq())
        .then(resp => {
          let data = resp.data || [];
          let dataStat = {
            fileCount: 0,
            total: 0,
            error: 0,
            success: 0
          };
          let fileMapper = {};
          data.forEach(item => {
            dataStat.total += item.total;
            dataStat.fileCount++;
            dataStat.success += item.success;
            dataStat.error += item.total - item.success;
            fileMapper[item.uploadId] = {
              total: item.total,
              errCount: item.total - item.success
            };
          });
          this.fileResultMapper = fileMapper;
          this.fileList.forEach(fileInfo => {
            let statInfo = fileMapper[fileInfo.id];
            this.$set(fileInfo, 'total', statInfo ? statInfo.total : 0);
            this.$set(fileInfo, 'errCount', statInfo ? statInfo.errCount : 0);
          });
          this.resultInfo = dataStat;
          if (isUpload) {
            this.firstImportStat = dataStat;
            // this.$bus.$emit("updateResultInfo", this.resultInfo);
          }
        })
        .catch(this.onException);
    },

    /**
     *获取当前使用的序列号
     */
    getCurrentImportSeq() {
      return this.importSeq == this.lastImportSeq ? this.importSeq : this.lastImportSeq;
    },

    /**
     * 获取最后一次导入信息
     */
    queryLastUploadInfo() {
      this.excelImportApi
        .getLastImportSeq(this.id)
        .then(resp => {
          this.lastImportSeq = resp.data;
          this.fetchLastFileList();
        })
        .catch(this.onException);
    },

    /**
     * 获取最后一次导入文件列表
     */
    fetchLastFileList() {
      this.excelImportApi
        .fetchLastFileList(this.lastImportSeq)
        .then(resp => {
          this.fileList = resp.data;
          this.search();
          if (
            this.fileList.some(item => {
              return item.uploadStatus == 0;
            })
          ) {
            this.loadFileProcess();
          }
        })
        .catch(this.onException);
    },

    /**
     *列表单元格点击事件，启用编辑功能
     */
    handleRowClick(row, column, event) {
      if (!column || !column.property) {
        return;
      }
      // 行被点击，保存上一行，启用当前行
      this.tooltipDisabled = true;
      if (this.editingRow.id != row.id) {
        this.updateData();
        this.$set(row, '_input', true);
        this.editingRow = row;
        this.oriRow = {
          ...row
        };
      }
    },

    /**
     * 页面点击如果没在表格内取消编辑
     */
    handleOutsideClick(e) {
      this.updateData();
      this.editingRow = {};
      this.oriRow = {};
      this.tooltipDisabled = false;
    },
    updateData(editingRow, oriRow, dataSource) {
      // this.$set(this.editingRow, '_input', false); //todo
      editingRow._input = false;
      if (editingRow.id) {
        // 保存
        let rowData = {};
        let updated = false;
        for (var p in editingRow) {
          if (!_.startsWith(p, '_') && p != 'validateResult') {
            let value = editingRow[p];
            if (value instanceof Array) {
              // 数组，说明是多选
              rowData[p] = value.join(',');
            } else {
              rowData[p] = value;
            }
            if (oriRow[p] != value) {
              updated = true;
            }
          }
        }
        if (updated == false) {
          return;
        }
        this.excelImportApi
          .update(this.id, this.getCurrentImportSeq(), [rowData], this.requestParams)
          .then(resp => {
            let result = resp.data;
            if (result.statusCode === '200') {
              this.getImportStat();
              let data = result.result || [];
              let dataMapper = {};
              let count = 0;
              data.forEach(row => {
                dataMapper[row.id] = row;
                count++;
              });

              // let dataSource = this.$refs.dataGrid.dataSource || [];
              let coverCount = 0;
              for (var i = 0, len = dataSource.length; i < len; i++) {
                let row = dataSource[i];
                if (dataMapper[row.id]) {
                  this.$set(dataSource, i, dataMapper[row.id]);
                  coverCount++;
                  if (coverCount >= count) {
                    break;
                  }
                }
              }
            } else {
              this.$message.error('修改数据出错：' + result.message);
            }
          })
          .catch(this.onException);
      }
    },

    /**
     * 下载导入模板
     */
    handleDownloadTemplate() {
      let fileName = this.scheme.name + '-' + dateUtils.format(new Date(), 'yyyyMMdd') + '.' + this.scheme.fileType;
      this.excelImportApi.downloadTemplate(this.scheme.id, fileName);
    },

    /**
     * 选择删除
     */
    handleDelete() {
      let selects = this.$refs.dataGrid.currentSelected;
      if (selects.length == 0) {
        this.$message.warning('请选择数据后在进行删除！');
        return;
      }
      this.handleDeleteData(selects);
    },
    /**
     * 删除数据
     */
    handleDeleteData(selects) {
      this.$dgConfirm(`确定删除选择的数据?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.showLoading('删除中，请稍后...');
          let idArr = [];
          selects.forEach(row => {
            idArr.push(row.id);
          });
          this.excelImportApi
            .delete(this.scheme.id, this.getCurrentImportSeq(), idArr, this.requestParams)
            .then(resp => {
              this.hideLoading();
              let res = resp.data;
              if (res.statusCode == '200') {
                this.$message.success('删除成功！');
                this.search();
              } else {
                this.$message.error('删除失败：' + res.message);
              }
            })
            .catch(this.onException);
        })
        .catch(() => {});
    },

    /**
     * 清空错误数据
     */
    handleClear() {
      this.$dgConfirm(`确定删除所有错误数据?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.showLoading('删除中，请稍后...');
          this.excelImportApi
            .cleanErrorData(this.scheme.id, this.getCurrentImportSeq(), this.requestParams)
            .then(resp => {
              this.hideLoading();
              let res = resp.data;
              if (res.statusCode == '200') {
                this.$message.success('删除成功！');
                this.search();
              } else {
                this.$message.error('删除失败：' + res.message);
              }
            })
            .catch(this.onException);
        })
        .catch(() => {});
    },

    /**
     * 导出错误数据
     */
    handleExport() {
      let fileName =
        '错误数据(' +
        this.scheme.name +
        ')-' +
        dateUtils.format(new Date(), 'yyyyMMddHHmmss') +
        '-' +
        this.getCurrentImportSeq() +
        '.' +
        this.scheme.fileType;
      this.excelImportApi.exportErrorData(this.scheme.id, this.getCurrentImportSeq(), fileName);
    },

    /**
     * 选择导入
     */
    handleImport() {
      let selects = this.$refs.dataGrid.currentSelected;
      if (selects.length == 0) {
        this.$message.warning('请选择数据后在进行导入！');
        return;
      }
      this.handleImportData(selects);
    },

    handleImportData(selects) {
      let idArr = [];
      selects.forEach(item => {
        if (item.validateStatus == 1) {
          idArr.push(item.id);
        }
      });
      if (idArr.length == 0) {
        this.$message.warning('您选择的数据均为无效数据，无法导入！');
        return;
      }
      this.$dgConfirm(`确定导入选择的数据?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.showLoading('导入中，请稍后...');
          this.excelImportApi
            .importSelect(this.scheme.id, this.getCurrentImportSeq(), idArr, this.requestParams)
            .then(resp => {
              this.hideLoading();
              let res = resp.data;
              if (res.statusCode == '200') {
                this.$message.success(res.message);
                this.search();
              } else {
                this.$message.error('导入失败：' + res.message);
              }
            })
            .catch(this.onException);
        })
        .catch(() => {});
    },

    /**
     * 导入全部
     */
    handleImportAll(isSecond) {
      let that_ = this;
      if (isSecond === true && this.resultInfo.total == this.resultInfo.error) {
        this.$message.warning('当前不存在可以导入的数据！');
        return;
      }
      this.$dgConfirm(`确定导入全部有效数据?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          that_.showLoading('导入中，请稍后...');
          that_.excelImportApi
            .importAll(that_.scheme.id, that_.getCurrentImportSeq(), that_.requestParams)
            .then(resp => {
              that_.hideLoading();
              let res = resp.data;
              if (res.statusCode == '200') {
                that_.$message.success(res.message);
                that_.search();
                // 关闭失败详情弹窗
                that_.$bus.$emit('closeErrorList');
                if (isSecond === true) return;
                // 当不存在导入失败数据时，不显示失败弹框
                if (that_.firstImportStat['error'] != 0) {
                  var layer = this.$dgLayer({
                    title: '失败导入详情',
                    content: require('./errorList.vue'),
                    maxmin: false,
                    props: {
                      id: that_.id,
                      importSeq: that_.getCurrentImportSeq(),
                      scheme: that_.scheme,
                      defaultColumnWidth: that_.id == 'qtxx_imp_template' ? 212 : 495,
                      tooltipDisabled: that_.tooltipDisabled,
                      importStat: that_.firstImportStat,
                      treeData: that_.treeData,
                      excelImportApi: that_.excelImportApi
                    },
                    on: {
                      success(params) {
                        // 刷新最外层列表
                        that_.$bus.$emit('Success');
                        // 关闭导入窗口
                        that_.$emit('closeDialog');
                        // 关闭对应弹窗的ID
                        layer.close(layer.dialogIndex);
                      }
                    },
                    cancel: function(index, layero) {
                      // 关闭对应弹窗的ID
                      layer.close(index);
                      return false;
                    },
                    area: ['80%', '780px']
                  });
                } else {
                  // 刷新最外层列表
                  that_.$bus.$emit('Success');
                }
              } else {
                that_.$message.error('导入失败：' + res.message);
              }
            })
            .catch(that_.onException);
        })
        .catch(() => {});
    },

    /**
     * 删除附件
     */
    handleDeleteFile(fileInfo) {
      // 还未开始上传，直接从文件列表移除
      if (!fileInfo.id) {
        let index = _.findIndex(this.uploadFiels, item => {
          return item.clientId == fileInfo.clientId;
        });
        if (index > -1) {
          this.uploadFiels.splice(index, 1);
          index = _.findIndex(this.fileList, item => {
            return item.clientId == fileInfo.clientId;
          });
          index > -1 && this.fileList.splice(index, 1);
        }
      } else {
        this.$dgConfirm(`确定删除该文件[${fileInfo.fileName}]，并清空此文件的缓存数据?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            this.showLoading('删除中，请稍后...');
            this.excelImportApi
              .deleteFile(this.scheme.id, this.getCurrentImportSeq(), fileInfo.id, this.requestParams)
              .then(resp => {
                this.hideLoading();
                let res = resp.data;
                if (res.statusCode == '200') {
                  this.$message.success('删除成功！');
                  let index = _.findIndex(this.fileList, item => {
                    return item.id == fileInfo.id;
                  });
                  this.fileList.splice(index, 1);
                  this.search();
                } else {
                  this.$message.error('删除失败：' + res.message);
                }
              })
              .catch(this.onException);
          })
          .catch(() => {});
      }
    },

    /**
     * 文件导入
     * @param param
     * @returns {boolean}
     */
    uploadFile(param) {
      let file = param.file;
      let size = file.size;
      const { scheme, importSeq, fileLimitSize, supportType } = this;
      if (size > fileLimitSize * 1024 * 1024) {
        this.$message({
          message: `文件[${file.name}]上传失败，最大支持上传不大于(${fileLimitSize}M)的文件`,
          type: 'warning'
        });
        return false;
      }
      if (!supportType.split(',').includes(file.name.substring(file.name.lastIndexOf('.')))) {
        this.$message({
          message: `文件[${file.name}]上传失败，仅支持上传(${supportType})后缀的文件`,
          type: 'warning'
        });
        return false;
      }
      if (this.importSeq != this.lastImportSeq) {
        this.lastImportSeq = this.importSeq;
        this.fileList = [];
        // this.search();
        this.getImportStat(true);
      }
      let fileInfo = {
        index: 1,
        clientId: this.generateUUID(),
        fileName: file.name,
        fileSize: size,
        uploadStatus: 0,
        percentage: 0,
        uploadTime: '',
        file: file
      };
      this.fileList.unshift(fileInfo);
      this.uploadFiels.unshift({
        clientId: fileInfo.clientId,
        file: file
      });
      this.doUploadFiles();
    },
    /**
     * 上传文件
     */
    doUploadFiles() {
      // 找到最后面的三个文件进行上传
      while (this.uploadingNum < this.parallelNum && this.uploadFiels.length > 0) {
        let fileInfo = this.uploadFiels.pop();
        if (fileInfo) {
          this.excelImportApi
            .importExcel(this.scheme.id, this.importSeq, fileInfo.clientId, fileInfo.file, this.requestParams)
            .then(resp => {
              let result = resp.data;
              if (result.statusCode != '200') {
                this.$message.error(result.message);
                // 不符合要求文件自动删除
                if (this.fileList) {
                  this.fileList.splice(0, 1);
                }
              }
              this.uploadingNum--;
              if (this.uploadFiels.length > 0) {
                this.doUploadFiles();
              }
            })
            .catch(e => {
              this.$message.error('网络出现异常！');
            });
          this.uploadingNum++;
        }
      }
      if (this.uploadingNum > 0) {
        this.loadFileProcess();
      }
    },

    /**
     * 加载文件上传进度条
     */
    loadFileProcess() {
      if (this.loadingProcess) {
        return;
      }
      this.loadingProcess = true;
      this.loadUploadProcess();
    },

    /**
     * 循环获取上传进度
     */
    loadUploadProcess(processVo) {
      this.excelImportApi
        .loadUploadProcess(this.scheme.id, this.getCurrentImportSeq())
        .then(resp => {
          let res = resp.data;
          let clientMap = {};
          for (var i = 0, len = this.fileList.length; i < len; i++) {
            let fileInfo = this.fileList[i];
            clientMap[fileInfo.clientId] = i;
          }

          let hasFinish = false;
          for (var clientId in res) {
            let fileInfo = res[clientId];
            if (this.fileResultMapper[fileInfo.id]) {
              fileInfo.total = this.fileResultMapper[fileInfo.id].total;
              fileInfo.errCount = this.fileResultMapper[fileInfo.id].errCount;
            }
            this.$set(this.fileList, clientMap[clientId], fileInfo);
            if (fileInfo.uploadStatus != 0) {
              hasFinish = true;
            }
          }
          if (hasFinish) {
            // this.search();
            this.getImportStat(true);
          }

          if (
            this.fileList.some(item => {
              return item.uploadStatus == 0;
            })
          ) {
            // 还有没上传完的，继续刷新
            let timer = setTimeout(() => {
              clearTimeout(timer);
              this.loadUploadProcess();
            }, 1000);
          } else {
            // 上传完成
            this.loadingProcess = false;
          }
        })
        .catch(e => {
          // 错误了重新请求
          let timer = setTimeout(() => {
            clearTimeout(timer);
            this.loadUploadProcess();
          }, 200);
        });
    },

    /**
     * 生成文件列表序号
     */
    getFileIndex(index) {
      let pagination = this.$refs.fileGrid.paginationOptions;
      return (pagination.currentPage - 1) * pagination.pageSize + index + 1;
    },

    getDataIndex(index) {
      let pagination = this.$refs.dataGrid.paginationOptions;
      return (pagination.currentPage - 1) * pagination.pageSize + index + 1;
    },

    /**
     * 格式化文件大小
     */
    parseFileSize(size) {
      var result = '';
      var sizeM = parseInt(size / (1024 * 1024));
      var sizeK = parseInt(size / 1024);
      if (sizeM > 0) {
        result = (size / (1024 * 1024)).toFixed(2) + 'MB';
      } else if (sizeK > 0) {
        result = (size / 1024).toFixed(2) + 'KB';
      } else {
        result = size + 'byte';
      }
      return result;
    },

    /**
     * 格式化上传时间
     */
    parseUploadTime(uploadTime) {
      return dateUtils.strToDate(uploadTime, 'yyyyMMddHHmmss', 'yyyy-MM-dd HH-mm-ss', false);
    },

    /**
     * 格式化错误列表
     */
    getErrorList(validateResult) {
      let errs = [];
      for (var p in validateResult) {
        errs.push(
          '<span>' +
            this.fieldMapper[p].display +
            "：</span><span style='color: #F56C6C'>" +
            validateResult[p] +
            '</span>'
        );
      }
      return errs.join('<br/>');
    },

    /**
     *生成uuid
     * @returns {string}
     */
    generateUUID() {
      var d = new Date().getTime();
      if (window.performance && typeof window.performance.now === 'function') {
        d += performance.now();
      }
      var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
      });
      return uuid;
    },
    /**
     * 处理异常信息
     */
    onException(e) {
      this.hideLoading();
      this.$message.error('网络出现异常！');
    },

    // tooltip的可控
    visibilityChange(event, row, column) {
      if (row._input) {
        this.tooltipDisabled = true;
        return;
      }
      if (row.validateResult[column.name]) {
        this.tooltipDisabled = false;
      } else {
        const ev = event.target || event.srcElement;
        const ev_height = ev.offsetHeight; // 文本的实际高度
        const content_height = ev.scrollHeight; // 文本容器高度
        if (content_height <= ev_height) {
          this.tooltipDisabled = true;
        } else {
          this.tooltipDisabled = false;
        }
      }
    },

    /**
     * 显示遮罩
     */
    showLoading(text) {
      this.loadingBox = this.$loading({
        lock: true,
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.8)',
        text: text
      });
    },

    hideLoading() {
      this.loadingBox && this.loadingBox.close();
    }
  },
  directives: {
    clickoutside
  },
  components: {}
};
</script>

<style lang="scss">
.excel-import-page {
  .excel-import-bar {
    margin-bottom: 5px;
    justify-content: space-between;
    display: flex;
  }

  .file-tip {
    font-weight: bold;
    font-size: 14px;
  }

  .file-total {
    color: #409eff;
  }

  .file-success {
    color: #67c23a;
  }

  .file-error {
    color: #f56c6c;
  }

  .excel-import-file-list {
    .excel-import-file-table {
      td {
        font-size: 14px;
        padding: 5px 0px;
      }

      th {
        padding: 5px 0px;
      }

      .el-table .cell {
        line-height: 30px;
      }
    }

    .dg-table__pagination {
      padding: 5px;

      .el-pagination__total {
        float: left;
      }
    }

    .file-unupload {
      color: #409eff;
    }

    .file-uploading {
      color: #67c23a;
    }

    .file-upload-error {
      color: #f56c6c;
    }
  }

  .excel-import-data-list {
    margin-top: 5px;

    .excel-import-data-tab {
      line-height: 40px;

      .el-tabs {
        float: left;
      }

      .el-tabs__header {
        margin: 0px 0px 5px;
      }

      .import-data-toolbar {
        display: flex;
        justify-content: space-between;
        padding: 0px 0px 0px 10px;
      }
    }

    .excel-import-data-table {
      td {
        padding: 0px 0px;
      }

      th {
        padding: 5px 0px;
      }
    }

    .dg-table__pagination {
      padding: 5px;

      .el-pagination__total {
        float: left;
      }
    }

    .el-table .cell {
      padding: 0px;
      line-height: 30px;
    }

    .error-column {
      color: #f56c6c;
      border: 1px solid #f56c6c;
    }

    .tooltip-wrap {
      height: 32px; // 必须要有高度设置，因为tooltip的显示条件是通过高度来判断的
      line-height: 32px;
      display: -webkit-box;
      -webkit-line-clamp: 1; // 因为通过高度所以只显示一行，溢出显示省略号
      -webkit-box-orient: vertical;
      overflow: hidden;
      text-overflow: ellipsis;
      word-break: break-all; //英文数字折行
      margin: 1px;
      padding: 0px 5px;
    }

    .validate-status {
      font-size: 22px;
      line-height: 35px;

      &.status-success {
        color: #67c23a;
      }

      &.status-error {
        color: #f5222d;
      }
    }

    .ctr-btn {
      font-size: 20px;
      line-height: 35px;
    }
  }

  .template-download-item {
    color: #0063ea;
    margin-right: 10px;
    cursor: pointer;
  }

  .excel-import-footer {
    margin-top: 10px;
    text-align: center;
  }

  .excel-import-status-item {
    margin-bottom: 5px;
    padding-left: 70px;
  }

  .excel-import-status-info {
    font-size: 12px;
  }
}

.slide-fade-enter-active {
  transition: all 0s ease;
}

.slide-fade-leave-active {
  transition: all 0s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter,
  .slide-fade-leave-to

  /* .slide-fade-leave-active for below version 2.1.8 */ {
  transform: translateX(10px);
  opacity: 0;
}
</style>
